AWS Configの高度なクエリでOrganizations環境のS3に不完全なマルチパートアップロード削除が設定されていないバケットを検索してみた

AWS Configの高度なクエリでOrganizations環境のS3に不完全なマルチパートアップロード削除が設定されていないバケットを検索してみた

Clock Icon2024.10.21

こんにちは。
繁松です。

はじめに

AWSのベストプラクティスとして、S3のストレージコストを抑えるために不完全なマルチパートアップロード削除をライフサイクルポリシーに設定することが推奨されています。

AWS Organizations環境で多数のアカウントがある場合、どのS3バケットでこの設定が行われているかを確認するのは大変です。
本記事では、AWS Configの高度なクエリを使って、Organizations全体で不完全なマルチパートアップロード削除が設定されていないS3バケットを検索する方法を紹介します。

やってみた

前提条件

  • Configでリソースタイプ[S3 Bucket]の記録をしていること(検索したいリージョン全てで)
    • Config > 設定 > 記録するリソースタイプ を確認してください。
  • Configアグリゲータで組織のConfigを集約していること
    • 設定方法は以下のブログが参考になります。

https://dev.classmethod.jp/articles/config-aggregator-in-organization-member-account/

コンソールで検索

高度なクエリを使って、不完全なマルチパートアップロード削除が設定されていないS3バケットを検索します。

AWS Config > 高度なクエリ > [新しいクエリ]からクエリエディタを起動します。
2024-10-19_02h30_57

クエリスコープから組織のアグリゲータを指定します。
2024-10-19_02h35_19

  • クエリ
    • S3一覧を取得します。
    • マルチパートアップロードに設定されている日数で並べ替えます。
SELECT
  accountId,
  awsRegion,
  resourceName,
  supplementaryConfiguration.BucketLifecycleConfiguration.rules.abortIncompleteMultipartUpload.daysAfterInitiation
WHERE
  resourceType = 'AWS::S3::Bucket'
ORDER BY
  supplementaryConfiguration.BucketLifecycleConfiguration.rules.abortIncompleteMultipartUpload.daysAfterInitiation,
  accountId,
  awsRegion,
  resourceName

クエリを入力し実行します。

実行結果

高度なクエリではSQLのNULL値をサポートしていないのでS3の一覧を取得し、並べ替えた結果を目視で確認する必要があります。
値が「-」のバケットは不完全なマルチパートアップロード削除が設定されていません。

2024-10-19_02h53_13

AWS SDK for Pythonを使用して検索、一覧取得

コンソールからの検索では目視で確認する必要があるので、AWS SDK for Pythonを使用して不完全なマルチパートアップロード削除が設定されていないS3バケット一覧を取得します。

import boto3
import csv
import json

def execute_query(config_client, query, aggregator_name):
    paginator = config_client.get_paginator('select_aggregate_resource_config')
    page_iterator = paginator.paginate(Expression=query, ConfigurationAggregatorName=aggregator_name)

    results = []
    for page in page_iterator:
        for item in page['Results']:
            item_dict = json.loads(item)
            results.append(item_dict)

    return results

def main():
    config_client = boto3.client('config')
    aggregator_name = "アグリゲーター名"

    # マルチパートアップロードが設定されているS3バケットのクエリ
    multipart_query = """
    SELECT accountId, awsRegion, resourceName, supplementaryConfiguration.BucketLifecycleConfiguration.rules.abortIncompleteMultipartUpload.daysAfterInitiation
    WHERE resourceType = 'AWS::S3::Bucket'
    AND supplementaryConfiguration.BucketLifecycleConfiguration.rules.abortIncompleteMultipartUpload.daysAfterInitiation >= 0
    """

    # 全S3バケットのクエリ
    all_s3_query = """
    SELECT accountId, awsRegion, resourceName
    WHERE resourceType = 'AWS::S3::Bucket'
    """

    multipart_results = execute_query(config_client, multipart_query, aggregator_name)
    all_s3_results = execute_query(config_client, all_s3_query, aggregator_name)

    # マルチパートアップロードが設定されているS3バケットのセットを作成
    multipart_set = set((item['accountId'], item['awsRegion'], item['resourceName']) for item in multipart_results)

    file_name = 's3_without_multipart_lifecycle.csv'

    with open(file_name, mode='w', newline='') as csvfile:
        csv_writer = csv.writer(csvfile)

        csv_writer.writerow(['Account ID', 'Region', 'Resource Name'])

        # マルチパートアップロードが設定されていないS3バケットを書き込む
        for item in all_s3_results:
            if (item['accountId'], item['awsRegion'], item['resourceName']) not in multipart_set:
                csv_writer.writerow([item['accountId'], item['awsRegion'], item['resourceName']])

    return {
        'statusCode': 200,
        'body': 'CSV file with S3 buckets without multipart upload lifecycle policy created.'
    }

main()

実行結果

以下のようなcsvファイルが出力されます。

Account ID,Region,Resource Name
000000000000,ap-northeast-1,S3バケット名
111111111111,ap-northeast-1,S3バケット名

さいごに

不完全なマルチパートアップロード削除がライフサイクルポリシーに設定されていないS3の検索方法についてでした。
SDKを使用した方法ではLambda等と組み合わせることで定期的な通知を実施することも可能です。

Trusted Advisorでも検知することができるので、Organizations環境でTrusted Advisorを使った確認方法についても検証したいと思います。
https://dev.classmethod.jp/articles/trusted-advisor-s3-multipart-upload/

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.